package com.ruoyi.web.controller.client;


import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.ruoyi.common.annotation.Token;
import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.exception.user.UserException;
import com.ruoyi.common.jwt.AppUser;
import com.ruoyi.common.jwt.JwtUtil;
import com.ruoyi.common.jwt.LoginUser;
import com.ruoyi.common.utils.ServletUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.framework.encryption.AesEncryptUtils;
import com.ruoyi.framework.encryption.EncodeResponseBodyAdvice;
import com.ruoyi.framework.encryption.RSAUtils;
import com.ruoyi.framework.encryption.SecurityParameter;
import com.ruoyi.framework.shiro.service.SysPasswordService;
import com.ruoyi.framework.util.ShiroUtils;
import com.ruoyi.system.domain.SysDept;
import com.ruoyi.system.domain.SysDictData;
import com.ruoyi.system.domain.SysUser;
import com.ruoyi.system.service.ISysConfigService;
import com.ruoyi.system.service.ISysDeptService;
import com.ruoyi.system.service.ISysDictDataService;
import com.ruoyi.system.service.ISysUserService;
import com.ruoyi.web.controller.tool.Statics;
import com.ruoyi.yf.ITest.MedicalWaste;
import com.ruoyi.yf.domain.YfDept;
import com.ruoyi.yf.domain.YfHospitalIndividuationData;
import com.ruoyi.yf.domain.YfTag;
import com.ruoyi.yf.domain.interfaces.YfDepartment;
import com.ruoyi.yf.domain.interfaces.YfStaging;
import com.ruoyi.yf.service.IYfDeptService;
import com.ruoyi.yf.service.IYfHospitalIndividuationDataService;
import com.ruoyi.yf.service.IYfTagService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.models.auth.In;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpHeaders;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.stereotype.Controller;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import javax.print.attribute.standard.DocumentName;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.validation.Valid;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.math.BigDecimal;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

/**
 * XiaoYi...
 * 数据对接 接口
 * 95b6b182-087f-4726-8062-7844adfa6f7e
 */
@RequestMapping("/interface")
@Controller
@Api(tags = "对外数据接口")
@Validated
public class InterfaceController extends BaseController {


    @Autowired
    private ISysUserService userService;

    @Autowired
    private ISysDictDataService dictDataService;

    @Autowired
    private IYfTagService yfTagService;

    @Autowired
    private ISysDeptService sysDeptService;

    @Autowired
    private IYfDeptService yfDeptService;

    @Autowired
    private IYfHospitalIndividuationDataService gxhService;

    @Autowired
    private SysPasswordService passwordService;

    @Autowired
    private ISysConfigService configService;

    @Autowired
    JwtUtil tokenService;

    @Value("${token.header}")
    public String token_header;


    public static List<String> standardKSlist;
    public static SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    public static SimpleDateFormat daysdf = new SimpleDateFormat("yyyy-MM-dd");
    public String standardDeptCodePattern = "^A\\d{2,4}$";      // A + 2到4位数字
    public String idPattern = "^\\d{1,20}$";      // 数字 1-20位 验证 暂存点id 、科室id、收集入库出库人id
    public String trashTypePattern = "[1-6]";
    public String trashStatusPattern = "10|20|30";
    public String weightPattern = "(^[1-9](\\d+)?(\\.\\d{1,2})?$)|(^[1-9]$)|(^\\d\\.[1-9]{1,2}$)|(^\\d\\.[0]{1}[1-9]{1}$|(^\\d\\.[1-9]{1}[0]{1}$)$)";
    public String error = "2001";
    public String success = "2002";


    //117e3e73-1dbe-465f-aa94-5b3ec959c13a
    @PostMapping("/resetPwd")
    @ResponseBody
    public AjaxResult resetPwdSave(SysUser user) {
        // 密码验证
        if(StringUtils.isEmpty(user.getPassword())){
            return error("密码不能为空");
        }
        if( !user.getPassword().matches(Statics.regex1) ){
            return error("密码必须包含大写字母、小写字母、数字、特殊符号，且在8到20位之间");
        }
        userService.checkUserAllowed(user);
        user.setSalt(ShiroUtils.randomSalt());
        user.setPassword(passwordService.encryptPassword(user.getLoginName(), user.getPassword(), user.getSalt()));

        //验证用户名唯一
//        if (userService.checkLoginNameUnique(user.getLoginName()).equals("0")) {
            if (userService.resetUserPwd(user) > 0) {
                return success();
            }
//        }
        return error();
    }



    // 接收其它医院医废系统提交的医废数据接口
    //53950b19-f7bc-4f03-b913-2c6a466ab7d3
    @RequestMapping(method = {RequestMethod.POST}, value = "/receiveData")
    @ResponseBody
//     @SecurityParameter
//     @Token
    // public AjaxResult receiveData(@Valid @RequestBody(required = false) List<MedicalWaste> mwlist) {
    public HashMap<String, Object> receiveData(HttpServletRequest request, @RequestBody(required = false) String data) {

        Boolean isResultEncryption = true;     // 解密、加密开关

        // 生成16位对称加密AES秘钥
        String aseKey = EncodeResponseBodyAdvice.getRandomString(16);


        String token = request.getHeader(token_header);
        if( StringUtils.isEmpty(token)){
            AjaxResult ajaxResult = AjaxResultError("缺少token");
            String result = "";
            try {   // 直接用对称加密AES秘钥对结果加密
                result = isResultEncryption ? AesEncryptUtils.encrypt(JSON.toJSONString(ajaxResult), aseKey) : JSON.toJSONString(ajaxResult);
            } catch (Exception e) {
                e.printStackTrace();
            }

            System.out.println("  请求失败，返回结果： " + result );

            return getResultHashMap("N",aseKey,result);
        }
        System.out.println("  接收到的token： " + token );

        LoginUser loginUser = null;
        try{
            loginUser = tokenService.getLoginUser(token);
        }catch (Exception e){
            loginUser = null;
        }
        if( loginUser == null || loginUser.getUser() == null || loginUser.getUser().getUserId() == null ||
                loginUser.getUser().getDeptId() == null || StringUtils.isEmpty(loginUser.getPrivateKey()) ){
            AjaxResult ajaxResult = AjaxResultError("token无效");
            String result = "";
            try {   // 直接用对称加密AES秘钥对结果加密
                result = isResultEncryption ? AesEncryptUtils.encrypt(JSON.toJSONString(ajaxResult), aseKey) : JSON.toJSONString(ajaxResult);
            } catch (Exception e) {
                e.printStackTrace();
            }

            System.out.println("  请求失败，返回结果： " + result );

            return getResultHashMap("N",aseKey,result);
        }
        System.out.println("  token反查用户： " + loginUser.getUser().getUserId() + "   " + loginUser.getUser().getDeptId() );
        String privateKey = loginUser.getPrivateKey();
        System.out.println("  redis查到的私钥： " + privateKey );

        //============================        以上错误需要明文返回或对称密匙明文+内容加密        ======================//


        AjaxResult ajaxResult = parsingData(isResultEncryption,privateKey,loginUser.getUser().getDeptId(),data);

        String result = "";
        try {   // 直接用对称加密AES秘钥对结果加密
            result = isResultEncryption ? AesEncryptUtils.encrypt(JSON.toJSONString(ajaxResult), aseKey) : JSON.toJSONString(ajaxResult);
        } catch (Exception e) {
            e.printStackTrace();
        }
        // 使用RSA私钥对AES密匙加密
        String encrypted = RSAUtils.encryptedPrivateDataOnJava(aseKey, privateKey);

        System.out.println("  请求成功，返回结果： " + result );

        return getResultHashMap("Y",encrypted,result);
    }


    // 封装结果
    //ec5495bd-8f2a-4679-bb40-f5a9fd1e6222
    public HashMap<String, Object> getResultHashMap(String NY,String aseKey,String result){
        HashMap<String, Object> map = new HashMap<>();
        map.put("isUsePrivateKey",NY);     // N 时 直接用对称加密AES秘钥解密 ， Y 时 先用私钥解密AES秘钥 ， 再解密结果数据
        map.put("encrypted",aseKey);
        map.put("responseData",result );
        return map;
    }


    // 具体
    //519d975f-6c00-42e1-a442-b1a8dbce8419
    private AjaxResult parsingData(Boolean isResultEncryption, String privateKey, Long hospitalId, String data){

        if( StringUtils.isEmpty(data)){
            return AjaxResultError("请求体不能为空");
        }
        System.out.println("  接收到的字符串： " + data );

        // data 转 json   取出  encrypted    requestData
        JSONObject datajson = null;
        try{
            datajson = JSONObject.parseObject(data);
            if( StringUtils.isEmpty(datajson)){
                return AjaxResultError("请求体格式错误");
            }
        }catch (Exception e){
            return AjaxResultError("请求体格式错误");
        }

        String encrypted = datajson.getString("encrypted");         // 公钥加密后的对称加密密匙
        String requestData = datajson.getString("requestData");     // 对称加密密匙加密后的医废数据
        if( StringUtils.isEmpty(encrypted) || StringUtils.isEmpty(requestData) ){
            return AjaxResultError("请求体<encrypted>字段或<requestData>字段不能为空");
        }
        System.out.println("  encrypted：" + encrypted );
        System.out.println("  requestData：" + requestData );


        // 装到map进行解密
        Map<String, String> map = new HashMap<>();
        map.put("encrypted", encrypted);
        map.put("requestData", requestData);

        // AES解密用的字符集
        String AESDecryptionCharacterSet = configService.selectConfigByKey("yf.AESDecryption.characterSet");
        if( StringUtils.isEmpty(AESDecryptionCharacterSet) ){
            AESDecryptionCharacterSet = "utf-8";
        }

        // AES解密是否使用16进制字符串     false 不需要
        String hexStr = "false";
//        String hexStr = configService.selectConfigByKey("yf.AESDecryption.hexStr");
//        if( StringUtils.isEmpty(hexStr) ){
//            hexStr = "false";
//        }

        String encryptedRequestData = null;
        try{    // isResultEncryption: 是否需要私钥解密     hexStr: 是否需要转成十六进制加解密
            if(hexStr.equals("true")){
                encryptedRequestData = isResultEncryption ?
                        RSAUtils.privateKeyDecryptStringHex(map, privateKey, AESDecryptionCharacterSet) : requestData;
            }else{
                encryptedRequestData = isResultEncryption ?
                        RSAUtils.privateKeyDecryptString(map, privateKey, AESDecryptionCharacterSet) : requestData;
            }
            if(StringUtils.isEmpty(encryptedRequestData)){
                return AjaxResultError("请求体<requestData>字段不能被解密");
            }
        }catch (Exception e){
            return AjaxResultError("请求体<requestData>字段不能被解密");
        }
        System.out.println("  解密后医废数据：" + encryptedRequestData );

        // requestData 转成 List<MedicalWaste> mwlist
        List<MedicalWaste> mwlist;
        try{
            // mwlist = JSONObject.parseArray(encryptedRequestData, MedicalWaste.class);



            // 放过表中的暂存点 -- 如果个性化表里有放过，否则阻挡
            String backinfo = "请求体<requestData>字段不能被解密";
            List<YfHospitalIndividuationData> backstrlist =
                    gxhService.selectYfHospitalIndividuationDataList( new YfHospitalIndividuationData( "interfacebackstr" ) );
            if( backstrlist != null && !backstrlist.isEmpty() && !StringUtils.isEmpty(backstrlist.get(0).getDictValue()) ){
                backinfo = backstrlist.get(0).getDictValue();
            }
            try{
                mwlist = JSONObject.parseArray(encryptedRequestData, MedicalWaste.class);

                if( mwlist == null || mwlist.isEmpty() || StringUtils.isEmpty(mwlist.get(0).getStagingId()) ){
                    return AjaxResultError(backinfo);
                }
                Long sid = Long.parseLong( mwlist.get(0).getStagingId().trim() );
                List<YfHospitalIndividuationData> staginglist =
                        gxhService.selectYfHospitalIndividuationDataList( new YfHospitalIndividuationData( sid ) );
                if( staginglist == null || staginglist.isEmpty() ){
                    return AjaxResultError(backinfo);
                }

            }catch (Exception e){
                return AjaxResultError( backinfo );
            }



        }catch (Exception e){
            return AjaxResultError("<requestData>字段格式错误");
        }

        if( mwlist == null || mwlist.isEmpty() ){
            return AjaxResultError("医废数据不能为空");
        }

        if( mwlist.size() > 1000 ){
            return AjaxResultError("每次上传医废数据不能超过1000条");
        }


        // 验证MedicalWaste类里的注解
        for (MedicalWaste mw : mwlist) {
            if( StringUtils.isEmpty(mw.getCodeid()) ||  StringUtils.isEmpty(mw.getStagingId())
                    || StringUtils.isEmpty(mw.getBag()) || StringUtils.isEmpty(mw.getWeight()) ){
                return AjaxResultError(mw.getCodeid() + "医废 -- <codeid>或<stagingId>或<bag>或<weight>字段不能有空值");
            }
            if( mw.getCodeid().trim().length() > 50 || mw.getStagingId().trim().length() > 50
                    || !Pattern.matches(idPattern,mw.getStagingId().trim()) ){
                return AjaxResultError(mw.getCodeid() + "医废 -- <codeid>或<stagingId>字段长度不能超过50，<stagingId>只能是数字");
            }
            try{
                long bag = Long.parseLong(mw.getBag().trim());
                double weight = Double.parseDouble(mw.getWeight().trim());
                if( bag < 1 || weight <= 0 || !Pattern.matches(weightPattern,mw.getWeight().trim()) ){
                    return AjaxResultError(mw.getCodeid() + "医废 -- <bag>或<weight>字段格式错误");
                }
            }catch (Exception e){
                return AjaxResultError(mw.getCodeid() + "医废 -- <bag>或<weight>字段格式错误");
            }
            if(StringUtils.isEmpty(mw.getStandardDeptCode()) || StringUtils.isEmpty(mw.getSourceDeptId())
                    || StringUtils.isEmpty(mw.getSourceDeptName()) || StringUtils.isEmpty(mw.getTrashType())
                    || StringUtils.isEmpty(mw.getTrashStatus()) ){
                return AjaxResultError(mw.getCodeid()
                        + "医废 -- <standardDeptCode>或<sourceDeptId>或<sourceDeptName>或<trashType>或<trashStatus>字段不能有空");
            }
            if( !Pattern.matches(standardDeptCodePattern,mw.getStandardDeptCode().trim()) ||
                    !Pattern.matches(trashTypePattern,mw.getTrashType().trim()) ||
                    !Pattern.matches(trashStatusPattern,mw.getTrashStatus().trim()) ||
                    !Pattern.matches(idPattern,mw.getSourceDeptId().trim()) ){
                return AjaxResultError(mw.getCodeid()
                        + "医废 -- <standardDeptCode>或<trashType>或<trashStatus>字段格式错误，<sourceDeptId>只能是数字");
            }
            if(StringUtils.isEmpty(mw.getCollectUserId()) || StringUtils.isEmpty(mw.getCollectUserName())
                    || StringUtils.isEmpty(mw.getCollectUpdateDate()) ){
                return AjaxResultError(mw.getCodeid() + "医废 -- <collectUserId>或<collectUserName>或<collectUpdateDate>不能有空");
            }
            // 验证收集人id、入库人id、出库人id只能是数字
            if( !Pattern.matches(idPattern,mw.getCollectUserId().trim()) ){
                return AjaxResultError(mw.getCodeid() + "医废 -- <collectUserId>只能是数字");
            }
            if( !StringUtils.isEmpty(mw.getIntoUserId())){
                if( !Pattern.matches(idPattern,mw.getIntoUserId().trim()) ){
                    return AjaxResultError(mw.getCodeid() + "医废 -- <intoUserId>只能是数字");
                }
            }
            if( !StringUtils.isEmpty(mw.getOutUserId())){
                if( !Pattern.matches(idPattern,mw.getOutUserId().trim()) ){
                    return AjaxResultError(mw.getCodeid() + "医废 -- <outUserId>只能是数字");
                }
            }
        }


        // 标准科室
        if( standardKSlist == null || standardKSlist.isEmpty() ){
            standardKSlist = dictDataService.selectDictDataValueByType("yf_standard_dept_code");
        }
        // 验证医废条码是否有重复、验证标准科室在字典表是否都有、验证医院暂存点id
        HashSet<String> barset = new HashSet<>();       // 医废条码id
        HashSet<String> sdeptset = new HashSet<>();     // 标准科室编码
        HashSet<Long> stagingset = new HashSet<>();   // 暂存点id
        for (MedicalWaste medicalWaste : mwlist) {
            barset.add(medicalWaste.getCodeid());
            sdeptset.add(medicalWaste.getStandardDeptCode());
            stagingset.add(Long.parseLong(medicalWaste.getStagingId().trim()));
        }
        if(mwlist.size() != barset.size()){
            return AjaxResultError("<codeid>不能有重复");
        }
        for(String sdeptcode : sdeptset){
            if( !standardKSlist.contains(sdeptcode) ){
                return AjaxResultError("<standardDeptCode>填报错误");
            }
        }
        // 验证token拿到的用户所在的 医院id 与 暂存点id 能对应上 ， 用户建立在医院上 ， 根据用户所在的deptId查询暂存点id
        List<Long> deptlist = sysDeptService.getStagingIdByHospitalId(hospitalId);
        for (Long stagingId : stagingset) {
            if( !deptlist.contains(stagingId) ){
                return AjaxResultError("<stagingId>填报错误");
            }
        }


        String nowdate = daysdf.format(new Date());

        // 根据暂存点查询医院所有科室,以验证上传的科室id、科室名称、科室标准编码
        List<YfDept> kslist = yfDeptService.getKSlistByStagingId( Long.parseLong(mwlist.get(0).getStagingId().trim()) );
        if( kslist == null || kslist.isEmpty() ){
            return AjaxResultError("根据<stagingId>未能查询到科室");
        }

        // 验证数据正确性,分成两组
        List<YfTag> insertlist = new ArrayList<>();
        List<YfTag> updatelist = new ArrayList<>();
        Date now = new Date();
        for (MedicalWaste medicalWaste : mwlist) {

            // 验证上传的科室id、科室名称、科室标准编码
            YfDept ksbean = null;
            for (int i = 0; i < kslist.size(); i++) {
                if( medicalWaste.getSourceDeptId().equals( kslist.get(i).getDeptId() + "" ) ){
                    ksbean = kslist.get(i);
                    break;
                }
            }
            if( ksbean == null ){
                return AjaxResultError("根据科室id：" + medicalWaste.getSourceDeptId() + "，未能在平台查询到科室");
            }
            if( !medicalWaste.getSourceDeptName().equals( ksbean.getDeptName() ) ){
                return AjaxResultError("科室id为" + medicalWaste.getSourceDeptId() + "的科室，上传的<sourceDeptName>与平台返回的<sourceDeptName>不一致");
            }
            if( !medicalWaste.getStandardDeptCode().equals( ksbean.getStandardDeptCode() ) ){
                return AjaxResultError("科室id为" + medicalWaste.getSourceDeptId() + "的科室，上传的<standardDeptCode>与平台返回<standardDeptCode>不一致");
            }


            // 判断收集人、入库人、出库人、科室名称 是否乱码    || !checkNameChese(medicalWaste.getSourceDeptName())  先不检测科室名称中文乱码
            if( !checkNameChese(medicalWaste.getCollectUserName()) ){
                return AjaxResultError("加密时请使用UTF-8编码");
            }
            if( !StringUtils.isEmpty(medicalWaste.getIntoUserName()) ){
                if( !checkNameChese(medicalWaste.getIntoUserName()) ){
                    return AjaxResultError("加密时请使用UTF-8编码");
                }
            }
            if( !StringUtils.isEmpty(medicalWaste.getOutUserName()) ){
                if( !checkNameChese(medicalWaste.getOutUserName()) ){
                    return AjaxResultError("加密时请使用UTF-8编码");
                }
            }

            // 根据条码查询医废
            YfTag selectYf = yfTagService.selectYfTagById(medicalWaste.getCodeid());
            if( selectYf != null ){
                // 医废状态比对，如果医废已上传，当前上传的医废状态不能小于已上传状态    10：收集     20：入库    30：出库
                if( Integer.parseInt(selectYf.getTrashStatus()) >= Integer.parseInt(medicalWaste.getTrashStatus())){
                    // continue;
                    if( selectYf.getTrashStatus().equals("10") ){
                        return AjaxResultError(medicalWaste.getCodeid() + "医废已收集");
                    }else if( selectYf.getTrashStatus().equals("20") ){
                        return AjaxResultError(medicalWaste.getCodeid() + "医废已入库");
                    }else if( selectYf.getTrashStatus().equals("30") ){
                        return AjaxResultError(medicalWaste.getCodeid() + "医废已出库");
                    }
                }
                // 如果已上传，比对一下暂存点id
                if( !medicalWaste.getStagingId().equals(selectYf.getStagingId()+ "")){
                    return AjaxResultError(medicalWaste.getCodeid() + "医废与之前上传的暂存点id对应不上");
                }
                // 比对袋数、重量
                long mwBag = Long.parseLong(medicalWaste.getBag());
                if( mwBag != selectYf.getBag().longValue() ){
                    return AjaxResultError(medicalWaste.getCodeid() + "医废与之前上传的袋数对应不上");
                }
                // 转换重量
                double mwWeight = new BigDecimal( medicalWaste.getWeight() ).
                        setScale(2,BigDecimal.ROUND_HALF_UP).doubleValue();

                if( mwWeight != selectYf.getWeight().doubleValue() ){
                    return AjaxResultError(medicalWaste.getCodeid() + "医废与之前上传的重量对应不上");
                }
                if( !medicalWaste.getTrashType().equals(selectYf.getTrashType())){
                    return AjaxResultError(medicalWaste.getCodeid() + "医废与之前上传的医废类型对应不上");
                }
            }

            // 转换医废实体类
            YfTag yfTag = new YfTag();

            try{
                yfTag.setCollectUpdateDate(sdf.parse(medicalWaste.getCollectUpdateDate()));
                if( yfTag.getCollectUpdateDate().getTime() > now.getTime() ){
                    return AjaxResultError(medicalWaste.getCodeid() + "医废 -- 收集时间不能大于现在时间");
                }
            }catch (Exception e){
                return AjaxResultError(medicalWaste.getCodeid() + "医废 -- 收集时间格式错误");
            }

            // 入库时，入库三个字段不能有空，入库时间转换，入库时间>=收集时间；出库时，6个字段，时间格式，时间比较
            String yfstatus = medicalWaste.getTrashStatus();
            if( yfstatus.equals("20") || yfstatus.equals("30") ){    // 入库三字段
                if(StringUtils.isEmpty(medicalWaste.getIntoUserId()) || StringUtils.isEmpty(medicalWaste.getIntoUserName())
                        || StringUtils.isEmpty(medicalWaste.getIntoDate()) ){
                    return AjaxResultError(medicalWaste.getCodeid() + "医废 -- 入库人id、入库人姓名、入库时间不能有空");
                }
                try{
                    if( selectYf == null || ( selectYf != null && selectYf.getTrashStatus().equals("10")) ){
                        yfTag.setIntoDate(sdf.parse(medicalWaste.getIntoDate()));
                        if( selectYf == null ){  // 医废未上传，入库时间不能小于收集时间
                            if( yfTag.getCollectUpdateDate().getTime() > yfTag.getIntoDate().getTime() ){
                                return AjaxResultError(medicalWaste.getCodeid() + "医废 -- 收集时间不能大于入库时间");
                            }
                        }else{   // 医废已上传，无视收集时间，入库时间不能小于上传医废的收集时间
                            if( selectYf.getCollectUpdateDate().getTime() >= yfTag.getIntoDate().getTime() ){
                                return AjaxResultError(medicalWaste.getCodeid() + "医废 -- 收集时间不能大于入库时间");
                            }
                        }

                        yfTag.setIntoUserId(Long.parseLong(medicalWaste.getIntoUserId().trim()));
                        yfTag.setIntoUserName(medicalWaste.getIntoUserName().trim());
                    }
                }catch (Exception e){
                    return AjaxResultError(medicalWaste.getCodeid() + "医废 -- 入库时间格式错误");
                }

            }
            if( yfstatus.equals("30") ){    // 出库三字段
                if(StringUtils.isEmpty(medicalWaste.getOutUserId()) || StringUtils.isEmpty(medicalWaste.getOutUserName())
                        || StringUtils.isEmpty(medicalWaste.getOutDate()) ){
                    return AjaxResultError(medicalWaste.getCodeid() + "医废 -- 出库人id、出库人姓名、出库时间不能有空");
                }
                try{
                    yfTag.setOutDate(sdf.parse(medicalWaste.getOutDate()));
                    if( selectYf == null ){   // 医废未上传
                        if( yfTag.getIntoDate().getTime() > yfTag.getOutDate().getTime() ){
                            return AjaxResultError(medicalWaste.getCodeid() + "医废 -- 入库时间不能大于出库时间");
                        }
                    }else if( selectYf != null && selectYf.getTrashStatus().equals("20") ){
                        if( selectYf.getIntoDate().getTime() > yfTag.getOutDate().getTime() ){
                            return AjaxResultError(medicalWaste.getCodeid() + "医废 -- 入库时间不能大于出库时间");
                        }
                    }

                    yfTag.setOutUserId(Long.parseLong(medicalWaste.getOutUserId().trim()));
                    yfTag.setOutUserName(medicalWaste.getOutUserName().trim());
                }catch (Exception e){
                    return AjaxResultError(medicalWaste.getCodeid() + "医废 -- 出库时间格式错误");
                }

            }

            if( selectYf == null ){   // 数据库没有这条医废，收集、入库、出库时间只能是今天   nowdate
                if( !daysdf.format(yfTag.getCollectUpdateDate()).equals(nowdate) ){
                    return AjaxResultError("只能上传今天的医废");
                }
                if( yfTag.getIntoDate()!= null ){
                    if( !daysdf.format(yfTag.getIntoDate()).equals(nowdate) ){
                        return AjaxResultError("只能上传今天的医废");
                    }
                }
                if( yfTag.getOutDate()!= null ){
                    if( !daysdf.format(yfTag.getOutDate()).equals(nowdate) ){
                        return AjaxResultError("只能上传今天的医废");
                    }
                }
            }else{  // 数据库已经有这条医废，至少状态是 10 收集
                if(medicalWaste.getTrashStatus().trim().equals("20")){  // 当前提交的医废是 20 入库   入库时间应该是今天
                    if( !daysdf.format(yfTag.getIntoDate()).equals(nowdate) ){
                        return AjaxResultError(medicalWaste.getCodeid() + "医废 -- 入库时间不是今天");
                    }
                }
                if(medicalWaste.getTrashStatus().trim().equals("30")){  // 当前提交的医废是 20 入库
                    if( !daysdf.format(yfTag.getOutDate()).equals(nowdate) ){
                        return AjaxResultError(medicalWaste.getCodeid() + "医废 -- 出库时间不是今天");
                    }
                }
                // 数据库是10  传上来是 30  入库时间应该是今天
                if( selectYf.getTrashStatus().equals("10") && medicalWaste.getTrashStatus().trim().equals("30") ){
                    if( yfTag.getIntoDate() == null ){
                        return AjaxResultError(medicalWaste.getCodeid() + "医废 -- 入库时间不能为空");
                    }
                    if( !daysdf.format(yfTag.getIntoDate()).equals(nowdate) ){
                        return AjaxResultError(medicalWaste.getCodeid() + "医废 -- 入库时间不是今天");
                    }
                }
            }


            yfTag.setUpdateWay("4");
            yfTag.setCreateTime(now);
            yfTag.setUpdateTime(now);
            yfTag.setCodeid(medicalWaste.getCodeid().trim());
            yfTag.setStagingId(Long.parseLong(medicalWaste.getStagingId().trim()));
            yfTag.setStandardDeptCode(medicalWaste.getStandardDeptCode().trim());
            yfTag.setSourceDeptId(Long.parseLong(medicalWaste.getSourceDeptId().trim()));
            yfTag.setSourceDeptName(medicalWaste.getSourceDeptName().trim());
            yfTag.setTrashType(medicalWaste.getTrashType().trim());
            yfTag.setTrashStatus(medicalWaste.getTrashStatus().trim());
            yfTag.setBag(Long.parseLong(medicalWaste.getBag().trim()));
            yfTag.setWeight(Double.parseDouble(medicalWaste.getWeight().trim()));
            yfTag.setCollectUserId(Long.parseLong(medicalWaste.getCollectUserId().trim()));
            yfTag.setCollectUserName(medicalWaste.getCollectUserName().trim());
            // 如果是出库
            if( yfTag.getTrashStatus().equals("30") ){
                yfTag.setOutBag(yfTag.getBag());
                yfTag.setOutWeight(yfTag.getWeight());
            }else{
                yfTag.setOutBag(0L);
                yfTag.setOutWeight(0D);
            }

            if( selectYf != null ){   // 更新
                updatelist.add(yfTag);
            }else{      // 添加
                insertlist.add(yfTag);
            }
        }

        if( insertlist.size() > 0 ){
            yfTagService.insertInterfaceYfTagList(insertlist);
        }
        if( updatelist.size() > 0 ){
            yfTagService.updateInterfaceYfTagList(updatelist);
        }

        return AjaxResultSuccess();

    }



    // 请求错误 -- 加密返回
    //ab0418ae-9bab-4d1d-be77-f13e6c17032f
    public AjaxResult AjaxResultError(String msg){
        return AjaxResult.result_XY(error, getAjaxResultError(msg));
    }

    // 请求成功
    //3e870478-a868-49eb-ae20-8cec08595d03
    public AjaxResult AjaxResultSuccess(){
        Map<String, Object> body = new LinkedHashMap<>();
        body.put("timestamp", new Date());
        return AjaxResult.result_XY(success, body);
    }

    // 错误请求返回体
    //0fc9ffd3-7476-4029-be57-fb60f4b05e70
    public Map<String, Object> getAjaxResultError(String msg){
        Map<String, Object> body = new LinkedHashMap<>();
        body.put("timestamp", new Date());
        List<String> errors = new ArrayList<>();
        errors.add(msg);
        body.put("errors", errors);
        return body;
    }





//    @RequestMapping(method = {RequestMethod.POST}, value = "/receiveData2")
//    @ResponseBody
////    @SecurityParameter
////    @Token
//    public AjaxResult receiveData(@Valid @RequestBody(required = false) List<MedicalWaste> mwlist) {
//        if( mwlist == null || mwlist.isEmpty() ){
//            return AjaxResultError("医废数据不能为空");
//        }
//        if( mwlist.size() > 1000 ){
//            return AjaxResultError("每次上传医废数据不能超过1000条");
//        }
//        // 标准科室
//        if( standardKSlist == null || standardKSlist.isEmpty() ){
//            standardKSlist = dictDataService.selectDictDataValueByType("yf_standard_dept_code");
//        }
//        // 验证医废条码是否有重复、验证标准科室在字典表是否都有、验证医院暂存点id
//        HashSet<String> barset = new HashSet<>();
//        HashSet<String> sdeptset = new HashSet<>();
//        HashSet<String> stagingset = new HashSet<>();
//        for (MedicalWaste medicalWaste : mwlist) {
//            barset.add(medicalWaste.getCodeid());
//            sdeptset.add(medicalWaste.getStandardDeptCode());
//            stagingset.add(medicalWaste.getStagingId());
//        }
//        if(mwlist.size() != barset.size()){
//            return AjaxResultError("医废条码不能有重复");
//        }
//        for(String sdeptcode : sdeptset){
//            if( !standardKSlist.contains(sdeptcode) ){
//                return AjaxResultError("标准科室编码填报错误");
//            }
//        }
//        // TODO: 2020/8/1  验证医院的用户名、密码 或者 医院唯一标识  与 暂存点id 能对应上
//        // TODO: 2020/8/1  验证收集时间不能小于现在时间前推N天
//        // TODO: 2020/8/1  验证各医院医废条码不能有重复，区分本系统与其他系统，可在MedicalWaste类加标识字段
//
//        // 验证数据正确性,分成两组
//        List<YfTag> insertlist = new ArrayList<>();
//        List<YfTag> updatelist = new ArrayList<>();
//        Date now = new Date();
//        for (MedicalWaste medicalWaste : mwlist) {
//            // 根据条码查询医废
//            YfTag yf = yfTagService.selectYfTagById(medicalWaste.getCodeid());
//            if( yf != null ){
//                // 医废状态比对，如果医废已上传，当前上传的医废状态不能小于已上传状态
//                if( Integer.parseInt(yf.getTrashStatus()) >= Integer.parseInt(medicalWaste.getTrashStatus())){
//                    continue;
//                }
//                // 如果已上传，比对一下暂存点id
//                if( !medicalWaste.getStagingId().equals(yf.getStagingId()+ "")){
//                    return AjaxResultError(medicalWaste.getCodeid() + "医废与之前上传的暂存点id对应不上");
//                }
//                // 比对袋数、重量
//                if( !medicalWaste.getBag().equals(yf.getBag()+ "")){
//                    return AjaxResultError(medicalWaste.getCodeid() + "医废与之前上传的袋数对应不上");
//                }
//                if( !medicalWaste.getWeight().equals(yf.getWeight()+ "")){
//                    return AjaxResultError(medicalWaste.getCodeid() + "医废与之前上传的重量对应不上");
//                }
//                if( !medicalWaste.getTrashType().equals(yf.getTrashType())){
//                    return AjaxResultError(medicalWaste.getCodeid() + "医废与之前上传的医废类型对应不上");
//                }
//            }
//
//            // 转换医废实体类
//            YfTag yfTag = new YfTag();
//
//            try{
//                yfTag.setCollectUpdateDate(sdf.parse(medicalWaste.getCollectUpdateDate()));
//                if( yfTag.getCollectUpdateDate().getTime() > now.getTime() ){
//                    return AjaxResultError(medicalWaste.getCodeid() + "医废 -- 收集时间不能大于现在时间");
//                }
//            }catch (Exception e){
//                return AjaxResultError(medicalWaste.getCodeid() + "医废 -- 收集时间格式错误");
//            }
//            // TODO: 2020/8/1  验证收集时间不能小于现在时间前推N天
//
//            // 入库时，入库三个字段不能有空，入库时间转换，入库时间>=收集时间；出库时，6个字段，时间格式，时间比较
//            String yfstatus = medicalWaste.getTrashStatus();
//            if( yfstatus.equals("20") || yfstatus.equals("30") ){    // 入库三字段
//                if(StringUtils.isEmpty(medicalWaste.getIntoUserId()) || StringUtils.isEmpty(medicalWaste.getIntoUserName())
//                        || StringUtils.isEmpty(medicalWaste.getIntoDate()) ){
//                    return AjaxResultError(medicalWaste.getCodeid() + "医废 -- 入库人id、入库人姓名、入库时间不能有空");
//                }
//                try{
//                    if( yf == null || ( yf != null && yf.getTrashStatus().equals("10")) ){
//                        yfTag.setIntoDate(sdf.parse(medicalWaste.getIntoDate()));
//                        if( yf == null ){  // 医废未上传，入库时间不能小于收集时间
//                            if( yfTag.getCollectUpdateDate().getTime() > yfTag.getIntoDate().getTime() ){
//                                return AjaxResultError(medicalWaste.getCodeid() + "医废 -- 收集时间不能大于入库时间");
//                            }
//                        }else{   // 医废已上传，无视收集时间，入库时间不能小于上传医废的收集时间
//                            if( yf.getCollectUpdateDate().getTime() >= yfTag.getIntoDate().getTime() ){
//                                return AjaxResultError(medicalWaste.getCodeid() + "医废 -- 收集时间不能大于入库时间");
//                            }
//                        }
//
//                        yfTag.setIntoUserId(Long.parseLong(medicalWaste.getIntoUserId()));
//                        yfTag.setIntoUserName(medicalWaste.getIntoUserName());
//                    }
//                }catch (Exception e){
//                    return AjaxResultError(medicalWaste.getCodeid() + "医废 -- 入库时间格式错误");
//                }
//
//            }
//            if( yfstatus.equals("30") ){    // 出库三字段
//                if(StringUtils.isEmpty(medicalWaste.getOutUserId()) || StringUtils.isEmpty(medicalWaste.getOutUserName())
//                        || StringUtils.isEmpty(medicalWaste.getOutDate()) ){
//                    return AjaxResultError(medicalWaste.getCodeid() + "医废 -- 出库人id、出库人姓名、出库时间不能有空");
//                }
//                try{
//                    yfTag.setOutDate(sdf.parse(medicalWaste.getOutDate()));
//                    if( yf == null ){   // 医废未上传
//                        if( yfTag.getIntoDate().getTime() > yfTag.getOutDate().getTime() ){
//                            return AjaxResultError(medicalWaste.getCodeid() + "医废 -- 入库时间不能大于出库时间");
//                        }
//                    }else if( yf != null && yf.getTrashStatus().equals("20") ){
//                        if( yf.getIntoDate().getTime() > yfTag.getOutDate().getTime() ){
//                            return AjaxResultError(medicalWaste.getCodeid() + "医废 -- 入库时间不能大于出库时间");
//                        }
//                    }
//
//                    yfTag.setOutUserId(Long.parseLong(medicalWaste.getOutUserId()));
//                    yfTag.setOutUserName(medicalWaste.getOutUserName());
//                }catch (Exception e){
//                    return AjaxResultError(medicalWaste.getCodeid() + "医废 -- 出库时间格式错误");
//                }
//
//            }
//
//
//            yfTag.setUpdateWay("4");
//            yfTag.setCreateTime(now);
//            yfTag.setUpdateTime(now);
//            yfTag.setCodeid(medicalWaste.getCodeid());
//            yfTag.setStagingId(Long.parseLong(medicalWaste.getStagingId()));
//            yfTag.setStandardDeptCode(medicalWaste.getStandardDeptCode());
//            yfTag.setSourceDeptId(Long.parseLong(medicalWaste.getSourceDeptId()));
//            yfTag.setSourceDeptName(medicalWaste.getSourceDeptName());
//            yfTag.setTrashType(medicalWaste.getTrashType());
//            yfTag.setTrashStatus(medicalWaste.getTrashStatus());
//            yfTag.setBag(Long.parseLong(medicalWaste.getBag()));
//            yfTag.setWeight(Double.parseDouble(medicalWaste.getWeight()));
//            yfTag.setCollectUserId(Long.parseLong(medicalWaste.getCollectUserId()));
//            yfTag.setCollectUserName(medicalWaste.getCollectUserName());
//
//            if( yf != null ){   // 更新
//                updatelist.add(yf);
//            }else{      // 添加
//                insertlist.add(yf);
//            }
//        }
//
//        if( insertlist.size() > 0 ){
//            yfTagService.insertInterfaceYfTagList(insertlist);
//        }
//        if( updatelist.size() > 0 ){
//            yfTagService.updateInterfaceYfTagList(updatelist);
//        }
//
//        return AjaxResultSuccess();
//    }



    @GetMapping("/aes")
    public String TextAes() {
        return "/aes";
    }




    @PostMapping(value = "/getPrivateKey")
    @ResponseBody
    public AjaxResult login(@RequestBody(required = false) String data) {
        if( StringUtils.isEmpty(data)){
            return AjaxResult.error("请求体不能为空");
        }
        System.out.println("  接收到的字符串： " + data );

        // data 转 json   取出  userName    password
        JSONObject datajson = null;
        try{
            datajson = JSONObject.parseObject(data);
            if( StringUtils.isEmpty(datajson)){
                return AjaxResult.error("请求体格式错误");
            }
        }catch (Exception e){
            return AjaxResult.error("请求体格式错误");
        }
        String userName = datajson.getString("userName");
        String password = datajson.getString("password");
        if( StringUtils.isEmpty(userName) || StringUtils.isEmpty(password) || userName.length() > 30 || password.length() > 30 ){
            return AjaxResult.error("请求体<userName>字段或<password>字段格式错误,字段长度不能超过30位");
        }
        System.out.println("  userName：" + userName );
        System.out.println("  password：" + password );

        SysUser sysUser = userService.selectUserByLoginName(userName);
        if (sysUser == null) {
            // throw new UserException("user.not.exists", null);
            return AjaxResult.error("用户名不存在/密码错误");
        }
        AppUser user = new AppUser(sysUser.getLoginName(), sysUser.getPassword(), sysUser.getSalt(), sysUser.getUserId(), sysUser.getDeptId());
        if (!JwtUtil.matches(user, password)) {
            // throw new UserException("user.not.exists", null);
            return AjaxResult.error("用户名不存在/密码错误");
        }
        AjaxResult ajax = AjaxResult.result_XY("200");

        Map<String, Object> stringObjectMap = null;
        String privateKey = null;
        String publicKey = null;
        LoginUser loginUser = new LoginUser(user);
        try {
            stringObjectMap = RSAUtils.genKeyPair();
            publicKey = RSAUtils.getPublicKey(stringObjectMap);
            privateKey = RSAUtils.getPrivateKey(stringObjectMap);
            loginUser.setPrivateKey(privateKey);
            loginUser.setPublicKey(publicKey);
            ajax.put("publicKey", publicKey);
//            EncodeResponseBodyAdvice.SERVER_PRIVATE_KEY = privateKey;
//            DecodeRequestBodyAdvice.SERVER_PRIVATE_KEY = privateKey;
        } catch (Exception e) {
            e.printStackTrace();
        }

        // TODO: 2020/7/28  待优化 重复登录 清除缓存信息
        String token = tokenService.createToken(loginUser);
        ajax.put(Constants.TOKEN, token);


        if (token == null)
            return AjaxResult.error("登录失败");

        // 根据登录名(医院管理员)获取暂存点列表
        List<SysDept> stagingDept = sysDeptService.getStagingIdByLoginName(userName);

        // System.out.println(  "   长度： " + stagingDept.size()  + "   " + stagingDept.get(0).getDeptId()  + "    " + stagingDept.get(0).getDeptName() );

        if(stagingDept == null || stagingDept.isEmpty()){
            ajax.put("staging",new ArrayList<YfStaging>() );
        }else{
            List<YfStaging> staginglist = new ArrayList<>();
            for (int i = 0; i < stagingDept.size(); i++) {
                if( stagingDept.get(i).getDeptId() != null && !StringUtils.isEmpty(stagingDept.get(i).getDeptName()) ){
                    staginglist.add(new YfStaging(stagingDept.get(i).getDeptId(),stagingDept.get(i).getDeptName()));
                }
            }
            ajax.put("staging",staginglist );
        }

        // 根据登录名(医院管理员)获取医疗机构的科室列表
        List<YfDepartment> kslist = yfDeptService.getKslistByLoginName(userName);

        // System.out.println(  "   长度： " + stagingDept.size()  + "   " + stagingDept.get(0).getDeptId()  + "    " + stagingDept.get(0).getDeptName() );

        if(kslist == null || kslist.isEmpty()){
            ajax.put("kslist",new ArrayList<YfDepartment>() );
        }else{
            ajax.put("kslist",kslist );
        }



        return ajax;
    }



//    @PostMapping(value = "/getPrivateKey")
//    @ResponseBody
//    public AjaxResult login(@RequestBody String json, @RequestParam Map<String, String> params) {
//        String userName;
//        String password;
//        if (params.size() > 0) {
//            System.out.println(params);
//            userName = params.get("userName");
//            password = params.get("password");
//        } else {
//            System.out.println(json);
//            JSONObject account = JSONObject.parseObject(json);
//            userName = (String) account.get("userName");
//            password = (String) account.get("password");
//        }
//
//        SysUser sysUser = userService.selectUserByLoginName(userName);
//        if (sysUser == null) {
//            // throw new UserException("user.not.exists", null);
//            return AjaxResult.error("用户名不存在/密码错误");
//        }
//        AppUser user = new AppUser(sysUser.getLoginName(), sysUser.getPassword(), sysUser.getSalt(), sysUser.getUserId(), sysUser.getDeptId());
//        if (!JwtUtil.matches(user, password)) {
//            // throw new UserException("user.not.exists", null);
//            return AjaxResult.error("用户名不存在/密码错误");
//        }
//        AjaxResult ajax = AjaxResult.result_XY("200");
//
//        Map<String, Object> stringObjectMap = null;
//        String privateKey = null;
//        String publicKey = null;
//        LoginUser loginUser = new LoginUser(user);
//        try {
//            stringObjectMap = RSAUtils.genKeyPair();
//            publicKey = RSAUtils.getPublicKey(stringObjectMap);
//            privateKey = RSAUtils.getPrivateKey(stringObjectMap);
//            loginUser.setPrivateKey(privateKey);
//            loginUser.setPublicKey(publicKey);
//            ajax.put("publicKey", publicKey);
////            EncodeResponseBodyAdvice.SERVER_PRIVATE_KEY = privateKey;
////            DecodeRequestBodyAdvice.SERVER_PRIVATE_KEY = privateKey;
//        } catch (Exception e) {
//            e.printStackTrace();
//        }
//
//        // TODO: 2020/7/28  待优化 重复登录 清除缓存信息
//        String token = tokenService.createToken(loginUser);
//        ajax.put(Constants.TOKEN, token);
//        if (token == null)
//            return AjaxResult.error("登陆失败");
//        return ajax;
//    }




    /**
     * 校验String是否全是中文
     *
     * @param name
     *      被校验的字符串
     * @return true代表全是汉字
     */
    public static boolean checkNameChese(String name) {
        boolean res = true;
        char[] cTemp = name.toCharArray();//转换为数组
        for (int i = 0; i < name.length(); i++) {
            if (!isChinese(cTemp[i])) {//逐个判断是否为中文
                res = false;
                break;
            }
        }
        return res;
    }


    /**
     * 判定输入的是否是汉字
     *
     * @param c
     *      被校验的字符
     * @return true代表是汉字
     */
    public static boolean isChinese(char c) {
        Character.UnicodeBlock ub = Character.UnicodeBlock.of(c);
        if (ub == Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS
                || ub == Character.UnicodeBlock.CJK_COMPATIBILITY_IDEOGRAPHS
                || ub == Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS_EXTENSION_A
                || ub == Character.UnicodeBlock.GENERAL_PUNCTUATION
                || ub == Character.UnicodeBlock.CJK_SYMBOLS_AND_PUNCTUATION
                || ub == Character.UnicodeBlock.HALFWIDTH_AND_FULLWIDTH_FORMS) {
            return true;
        }
        return false;
    }



}
